package ControllerLayer;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import ModelLayer.Direction;
import ModelLayer.Game;
import ModelLayer.Room;
import ModelLayer.RoomCharacter;
import ModelLayer.Tile;
import RenderLayer.RoomView;
import RenderLayer.View;
import ServiceLayer.Input;
import android.content.Context;
import android.graphics.Point;
import android.media.MediaPlayer;

import com.example.genericrpg_android.GameEngine;
import com.example.genericrpg_android.R;

public class RoomController extends Controller {
	Context activity;
	private RoomCharacter mCharacter;
	private GameEngine mEngine;
	private boolean battleArea, newBattle, checkOneTime,
					moving	= false,  
					lock	= false;
	
	public boolean masterLock = false;
	private int direction;
	private Game mModel;
	private Room room;
	private RoomView view;
	private Point pix, tile;
	private Tile cTile;
	private Timer timer = null;
	private Room nextRoom;
	private MediaPlayer player;
	private long sysTime;
	private long tEnd;
	private boolean scoreNotSet = true;
	private int time;
	
	public RoomController(Game model, GameEngine engine, Context activity){
		this.activity = activity;
		player = MediaPlayer.create(activity, R.raw.legendary_esper);
		mModel = model;
		mCharacter = model.getCharacter();
		mEngine = engine;
		view = new RoomView(model, engine.gameView);
		room = mModel.getCurrentRoom();	
		battleArea = true;
	}
	
	@Override
	public void handleInput(int input) {
		// TODO Auto-generated method stub
		if (!masterLock){
			checkOneTime = true;
			
			switch(input){
			case Input.DOWN: 
				handleDirection(Direction.DOWN);
				break;
			case Input.UP:
				handleDirection(Direction.UP);
				break;
			case Input.LEFT: 
				handleDirection(Direction.LEFT);
				break;
			case Input.RIGHT:
				handleDirection(Direction.RIGHT);
				break;
			case Input.A:
				break;
			case Input.B:
				mEngine.currentController = mEngine.pauseMenuController;
				mEngine.printControllerName();
				break;
			}	
		}
	}


	public void update() {
		
		room = mModel.getCurrentRoom();
		
		pix = mCharacter.pixelPosition;
		tile = mCharacter.tilePosition;

		cTile = room.getCurrentTile(mCharacter.getTilePosition());
		if(cTile.getValue() == Tile.DOOR_TILE || cTile.getValue() == Tile.END_TILE)
			masterLock = true;
		else
			masterLock = false;
		if(moving){
			// if Character position arrived at the next tile
			if(pix.x == tile.x*32 && pix.y == tile.y*32){
				moving = false;
				lock = false;
				generateNewBattle();
				// Check the tile values 
				if(cTile.getValue() == Tile.DOOR_TILE)
					setDelay(800);
				else if (cTile.getValue() == Tile.END_TILE && !room.restarting){
					setDelay(2000);
					TimerTask task = new TimerTask() {
						// Delays the loading of a room (allowing the view to fade in and out)
						@Override
						public void run() {
							if (scoreNotSet){
								time = room.time;
								scoreNotSet = false;
							}
							if(room.score < time)
								room.score += 1;
							else {
								scoreNotSet = true;
								timer.cancel();
								
								TimerTask task = new TimerTask() {
									// Delays the loading of a room (allowing the view to fade in and out)
									@Override
									public void run() {
										mEngine.currentController = mEngine.pauseMenuController;
									}
								};
								timer = new Timer();
								timer.schedule(task, 1800);
							}
						}
					};
					timer = new Timer();
					timer.scheduleAtFixedRate(task, 0, 30);
				}
				else if (battleArea && newBattle) {
					newBattle = false;
					player.stop();
					mEngine.startNewBattle();
				}
				String test = "Character moved '"+direction+"'! ";
				test += "<<"+mCharacter.getTilePosition().toString()+">>";
				System.out.println(test); 

			} else {
				mCharacter.move(direction);
			}
		}
	
		if (!room.timeSet){
			setUpTimer(30);
		}
		updateTimer();
	}

	private void setUpTimer(int time){
		sysTime = System.currentTimeMillis()/100;	
		tEnd = sysTime + time*10;
		room.timeSet = true;
	}
	
	public void wakeTimer() {
		sysTime = System.currentTimeMillis()/100;	
		tEnd = sysTime + room.time;
	}
	
	private void updateTimer() {
		sysTime = System.currentTimeMillis()/100;	
		room.time = (int) (tEnd - sysTime);
		
		if(room.time == 0){
			mEngine.gameView.move = false;
			room.timeOut = true;
			TimerTask task = new TimerTask() {
				// Delays the loading of a room (allowing the view to fade in and out)
				@Override
				public void run() {
					mEngine.currentController = mEngine.pauseMenuController;
					room.timeOut = false;
				}
			};
			timer = new Timer();
			timer.schedule(task, 2000);
		}
	}


	private void handleDirection(int direction) {
		mCharacter.setFacingDirection(direction);
		if (!lock)
			moving = setMotion(direction);
	}

	private void setDelay(int delay) {
		lock = true;
		if (checkOneTime){
			TimerTask task = createNewTask();
			timer = new Timer();
			timer.schedule(task, delay);
			checkOneTime = false;
		}
	}

	private TimerTask createNewTask() {
		TimerTask task = new TimerTask() {
			// Delays the loading of a room (allowing the view to fade in and out)
			@Override
			public void run() { 
				if (room.getTargets().get(tile) != null){
					String link = room.getTargets().get(tile);
					if (link.equals("random")) {
						Random generator = new Random();
						nextRoom = new Room("room" + (generator.nextInt(1) + 1), activity);
					} else {
						String[] result = link.split("#", 2);
						String from = result[0];
						String to = result[1];
						nextRoom = new Room(from, to, mCharacter, activity);
					}
					System.out.println("POSITION: "+tile.toString());
					mCharacter.setTilePosition(nextRoom.getStartPosition());
					mModel.setCurrentRoom(nextRoom);
					masterLock = false;
					lock = false;
				}
			}
		};
		return task;
	}

	private boolean setMotion(int dir) {
		this.direction = dir;
		boolean emptyTile;
		Point ctp = mCharacter.getTilePosition();
		emptyTile = room.isAdjacentTileEmpty(dir, ctp);
		if (emptyTile){
			mCharacter.changeTilePosition(dir);
			lock = true;
			return true;
		} else {
			System.out.println("You hit a wall!");
			return false;
		}
	}

	@Override
	public View getView() {
		return view;
	}
	
	public void playMusic(){
		if (!player.isPlaying()) {
			player = MediaPlayer.create(activity, R.raw.legendary_esper);
			player.start();
		}
	}
	
	public void stopMusic() {
		player.stop();
	}
	
	private boolean generateNewBattle() {
		Random generator = new Random();
		if (generator.nextInt(100) == 0) {
			newBattle = true;
		} else {
			newBattle = false;
		}		
		return newBattle;
	}
	
	public void restartRoom(){
		stopMusic();
		room.restarting = true;
		TimerTask task = new TimerTask() {
			// Delays the loading of a room (allowing the view to fade in and out)
			@Override
			public void run() {
				nextRoom = new Room(room.getName(), activity);
				mCharacter.setTilePosition(nextRoom.getStartPosition());
				mModel.setCurrentRoom(nextRoom);
				room.restarting = false;
				masterLock = false;
				lock = false;
			}
		};
		timer = new Timer();
		timer.schedule(task, 1000);
		playMusic();
	}
}
